
#ifndef __HW_APP_LOG_H__
#define __HW_APP_LOG_H__

#include "hw_app_config.h"
#include "spdlog/spdlog.h"
#include <spdlog/fmt/bundled/printf.h>

extern std::shared_ptr<spdlog::logger> logger;

template <class loggerPtr, class... Args>
void loglineprintf(loggerPtr                 logger,
    spdlog::level::level_enum level,
    spdlog::source_loc        loc,
    const char* fmt,
    const Args&... args) noexcept
{
    if (logger && logger->should_log(level))
    {
        // if (LOG_DEBUG_LEVEL) {
        //     printf("fmt: %s\n", fmt);
        //     printf(fmt, args...);
        //     printf("\n");
        // }
        try {
            logger->log(loc, level, "{}", fmt::sprintf(fmt, args...));
        } catch (std::exception& e) {
            printf("[ERROR]: log fmt may be error: \n");
            printf("fmt: %s\n", fmt);
            printf("\n");
        }
    }
}

#define SPDLOG_LOGGER_PRINTF(logger, level, ...) \
    loglineprintf(logger, level, spdlog::source_loc{__FILE__, __LINE__, SPDLOG_FUNCTION}, __VA_ARGS__)

//specific log implementation macros
#define LOG_DEBUG(...) SPDLOG_LOGGER_PRINTF(logger,spdlog::level::debug,__VA_ARGS__)
#define LOG_INFO(...) SPDLOG_LOGGER_PRINTF(logger,spdlog::level::info,__VA_ARGS__)
#define LOG_WARN(...) SPDLOG_LOGGER_PRINTF(logger,spdlog::level::warn,__VA_ARGS__)
#define LOG_ERROR(...) SPDLOG_LOGGER_PRINTF(logger,spdlog::level::err,__VA_ARGS__)

#define LOG_ASSERT(fmt, arg...)

#define LOG_IF_FAIL(expr, msgfmt, args...)     \
    do {if (!(expr)) { LOG_ERROR(msgfmt, ##args); }} while (0) 

#define ITGT_RETURN_DO_IF_FAIL(model, expr, func, msgfmt, args...) \
    /*lint -save -e717*/ do {                                        \
        if (!(expr)) {                                             \
            LOG_ERROR(msgfmt, ##args);               \
            func();                                                \
            return;                                                \
        }                                                          \
    } while (0) /*lint -restore*/
#define ITGT_RETURN_IF_FAIL(model, expr, msgfmt, ...)     \
    /*lint -save -e717*/ do {                               \
        if (!(expr)) {                                    \
            LOG_INFO_PRINT(model, msgfmt, __VA_ARGS__); \
            return;                                       \
        }                                                 \
    } while (0) /*lint -restore*/

#define ITGT_RETURN_VAL_SHOW_ERR_IF_FAIL(model, expr, ret, msgfmt, args...)                 \
    /*lint -save -e717*/ do {                                                                 \
        if (!(expr)) {                                                                      \
           fprintf(stderr, "[%s] [%s][%04d][%s]" msgfmt "\n",model,  __FILE__, __LINE__, __FUNCTION__, ##args); \
            return ret;                                                                     \
        }                                                                                   \
    } while (0) /*lint -restore*/


#define ITGT_ERROR_PRINT(model, dbgflag, fmt, ...) do { \
    printf("error ITGT_ERROR_PRINT");\
} while(0)

#define ITGT_INFO_PRINT(model, fmt, args...) do { \
    printf("error ITGT_INFO_PRINT");\
} while(0)

#define ITGT_LOG_IF_FAIL(model, expr, msgfmt, args...) \
    /*lint -save -e717*/ do {                            \
        if (!(expr)) {                                 \
            ITGT_ERROR_PRINT(model, msgfmt, ##args);   \
        }                                              \
    } while (0) /*lint -restore*/

#define ITGT_RETURN_VAL_IF_FAIL(model, expr, ret, msgfmt, ...) \
    /*lint -save -e717*/ do {                                    \
        if (!(expr)) {                                         \
            ITGT_ERROR_PRINT(model, msgfmt, __VA_ARGS__);      \
            return ret;                                        \
        }                                                      \
    } while (0) /*lint -restore*/

// extern int g_running;


// #ifdef __cplusplus
// }
// #endif

#endif